//package com.tyhy.jwt.service.impl;
//
//import cn.hutool.core.util.StrUtil;
//import com.alibaba.fastjson.JSON;
//import com.alibaba.fastjson.JSONObject;
//import com.tyhy.jwt.service.IJwtService;
//import com.tyhy.jwt.utils.JwtUtil;
//import com.tyhy.jwt.utils.RandomCodeUtil;
//import com.tyhy.program.cbc.mobileapi.util.RedisManager;
//import io.jsonwebtoken.Claims;
//import io.jsonwebtoken.JwtBuilder;
//import io.jsonwebtoken.Jwts;
//import io.jsonwebtoken.SignatureAlgorithm;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.lang3.StringUtils;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.stereotype.Service;
//
//import javax.crypto.SecretKey;
//import javax.servlet.http.HttpServletRequest;
//import java.util.Date;
//
///**
// * jwt service 实现类
// *
// * @author chenxu
// * @since 2020年07月25日
// */
//@Service
//@Slf4j
//public class JwtServiceImpl implements IJwtService {
//
//    @Value("${com.tyhy.jwt.key}")
//    private String key;
//
//    @Value("${com.tyhy.jwt.id}")
//    private String id;
//
//    @Value("${com.tyhy.jwt.issuser}")
//    private String issuser;
//
//    /** 混淆开始位置 */
//    private static final Integer SOLT_START = 25;
//    /** 混淆长度 */
//    private static final Integer SOLT_LENGTH = 32;
//
//    @Value("${com.tyhy.jwt.effective-time}")
//    private String effectiveTime;
//
//    @Value("${com.tyhy.jwt.database}")
//    private Integer database;
//
//
//    @Autowired
//    private RedisManager redisManager;
//
//    @Override
//    public String createJwt(String userId, Integer survivalTime) {
//        // 指定签名的时候使用的签名算法，也就是header那部分，jjwt已经将这部分内容封装好了。
//        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
//
//        // 生成JWT的时间
//        long nowMillis = System.currentTimeMillis();
//        Date now = new Date(nowMillis);
//
//        // 生成签名的时候使用的秘钥secret，切记这个秘钥不能外露哦。它就是你服务端的私钥，在任何场景都不应该流露出去。
//        // 一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。
//        SecretKey secretKey = JwtUtil.generalKey(key);
//
//        // 下面就是在为payload添加各种标准声明和私有声明了
//        JwtBuilder builder = Jwts.builder()
//                .setId(id)
//                .setIssuedAt(now)
//                .setIssuer(issuser)
//                .setSubject(userId)
//                .signWith(signatureAlgorithm, secretKey);
//
//        String jwtStr = deal(builder.compact());
//        String redisKey = JwtUtil.JWT_USER_KEY_PRE+userId;
//        //加入缓存 存活时间
//        JSONObject redisObj = new JSONObject();
//        redisObj.put("token",jwtStr);
//        redisObj.put("survivalTime",survivalTime);
//        redisManager.setEx(redisKey,(null == survivalTime ?getEffectiveTime():survivalTime),redisObj.toJSONString(),database);
//        return jwtStr;
//    }
//
//    /**
//     * 混淆 token
//     * @param jwtStr token
//     * @return {@link String}
//     * @since 2020/7/25
//     * 版本历史:
//     * Date         Author         Description
//     *---------------------------------------------------------*
//     * 2020/7/25   chenxu          初始创建
//     */
//    private String deal( String jwtStr ){
//        return StrUtil.sub(jwtStr,0, SOLT_START)+RandomCodeUtil.makeRandomCode(SOLT_LENGTH)+ StrUtil.subSuf(jwtStr, SOLT_START);
//    }
//
//    /**
//     * 解除混淆 token
//     * @param jwtStr token
//     * @return {@link String}
//     * @since 2020/7/25
//     * 版本历史:
//     * Date         Author         Description
//     *---------------------------------------------------------*
//     * 2020/7/25   chenxu          初始创建
//     */
//    private String dealBack( String jwtStr ){
//        return StrUtil.sub(jwtStr,0, SOLT_START)+ StrUtil.subSuf(jwtStr, SOLT_LENGTH + SOLT_START);
//    }
//
//    @Override
//    public boolean checkToken(String key, String jwt, HttpServletRequest request, String userIdHead) {
//        if (StringUtils.isEmpty(key) || StringUtils.isEmpty(jwt)) {
//            log.warn("jwt信息为空");
//            return false;
//        }
//
//        if (jwt.length() <= SOLT_START+SOLT_LENGTH){
//            log.warn("jwt:{},长度异常",jwt);
//            return false;
//        }
//
//        Claims claims = JwtUtil.parseJwt(key, dealBack(jwt));
//
//        // 根据实际业务需要处理subject中的内容
//        String subject = claims.getSubject();
//        //reqeust 增加 attribute jwtUserId,为解密后 userId
//        if (StringUtils.isEmpty(subject)){
//            log.warn("jwt:{},subject 解密后为 空,ip:{}",jwt,JwtUtil.getIPAddress(request));
//            return false;
//        }
//
//        if (!StringUtils.equals(userIdHead,subject)){
//            log.warn("jwt:{},subject 解密后 与head 中 userId 不符,ip:{}",jwt,JwtUtil.getIPAddress(request));
//            return false;
//        }
//
//        //根据 jwtUserId 确认 redis 中对应的 value 是否正确
//        String redisKey = JwtUtil.JWT_USER_KEY_PRE+subject;
//        String redisValue = redisManager.getRedisString(redisKey,database);
//
//        if (StringUtils.isEmpty(redisValue)){
//            log.warn("jwt:{},subject 解密后 不存在于redis 中,ip:{}",jwt,JwtUtil.getIPAddress(request));
//            return false;
//        }
//
//        JSONObject redisObj = JSON.parseObject(redisValue);
//        String jwtRedis = redisObj.getString("token");
//
//        if (!StringUtils.equals(jwt,jwtRedis)){
//            log.warn("jwt:{},subject 解密后,与 redis 对应的 value 不符,ip:{}",jwt,JwtUtil.getIPAddress(request));
//            return false;
//        }
//
//        request.setAttribute("jwtUserId",subject);
//        //通过 redis 延长缓存有效期
//        redisManager.setEx(redisKey,redisObj.getInteger("survivalTime"),redisValue,database);
//        return true;
//    }
//
//    /**
//     * 有效时间
//     *
//     * @return
//     */
//    private int getEffectiveTime() {
//        int time = Integer.parseInt(effectiveTime.substring(0, effectiveTime.length() - 1));
//        String unit = effectiveTime.substring(effectiveTime.length() - 1);
//
//        if ("s".equals(unit)) {
//            return time ;
//        }
//
//        if ("m".equals(unit)) {
//            return time * 60 ;
//        }
//
//        if ("h".equals(unit)) {
//            return time * 60 * 60 ;
//        }
//
//        if ("d".equals(unit)) {
//            return time * 24 * 60 * 60 ;
//        }
//
//        return -1;
//    }
//}
